﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Storage.Exceptions
{
    using EntityModels;

    #region TripNotFoundException

    /// <summary>
    /// This exception is thrown when a Trip is not found. 
    /// </summary>
    public class TripNotFoundException : Exception
    {
        private int _tripID;

        /// <summary>
        /// Gets the Message of the exception.
        /// </summary>
        public override string Message
        {
            get
            {
                return string.Format("No Trip exists with id: {0}", _tripID);
            }
        }

        /// <summary>
        /// Create a new instance of TripNotFoundException.
        /// </summary>
        /// <param name="tripID">The trip's id that was not found.</param>
        public TripNotFoundException(int tripID)
        {
            _tripID = tripID;
        }
    }

    #endregion

    #region EventNotFoundException

    /// <summary>
    /// This exception is thrown when an Event is not found. 
    /// </summary>
    public class EventNotFoundException : Exception
    {
        private int _eventID;

        /// <summary>
        /// Gets the Message of the exception.
        /// </summary>
        public override string Message
        {
            get
            {
                return string.Format("No Event exists with id: {0}", _eventID);
            }
        }

        /// <summary>
        /// Create a new instance of EventNotFoundException.
        /// </summary>
        /// <param name="eventID">The event's id that was not found.</param>
        public EventNotFoundException(int eventID)
        {
            _eventID = eventID;
        }
    }

    #endregion

    #region PlaceNotFoundException

    /// <summary>
    /// This exception is thrown when a Place is not found. 
    /// </summary>
    public class PlaceNotFoundException : Exception
    {
        private int _placeID;

        /// <summary>
        /// Gets the Message of the exception.
        /// </summary>
        public override string Message
        {
            get
            {
                return string.Format("No Place exists with id: {0}", _placeID);
            }
        }

        /// <summary>
        /// Create a new instance of PlaceNotFoundException.
        /// </summary>
        /// <param name="placeID">The place's id that was not found.</param>
        public PlaceNotFoundException(int placeID)
        {
            _placeID = placeID;
        }
    }

    #endregion

    #region StageNotFoundException

    /// <summary>
    /// This exception is thrown when a Stage is not found. 
    /// </summary>
    public class StageNotFoundException : Exception
    {
        private int _stageID;

        /// <summary>
        /// Gets the Message of the exception.
        /// </summary>
        public override string Message
        {
            get
            {
                return string.Format("No Stage exists with id: {0}", _stageID);
            }
        }

        /// <summary>
        /// Create a new instance of StageNotFoundException.
        /// </summary>
        /// <param name="stageID">The stage's id that was not found.</param>
        public StageNotFoundException(int stageID)
        {
            _stageID = stageID;
        }
    }

    #endregion

    #region UserNotFoundException

    /// <summary>
    /// This exception is thrown when an User is not found. 
    /// </summary>
    public class UserNotFoundException : Exception
    {
        private string _username;
        private int _userID;

        /// <summary>
        /// Create a new instance of UserNotFoundException.
        /// </summary>
        /// <param name="username">The username's user that was not found.</param>
        public UserNotFoundException(string username)
        {
            _username = username;
        }

        /// <summary>
        /// Create a new instance of UserNotFoundException.
        /// </summary>
        /// <param name="id">The user's id that was not found.</param>
        public UserNotFoundException(int id)
        {
            _userID = id;
        }

        /// <summary>
        /// Gets the Message of the exception.
        /// </summary>
        public override string Message
        {
            get
            {
                if (_username != null)
                    return "Invalid User: no user is already registered with this username: " + _username;
                else
                    return "Invalid User: no user is already registered with this id: " + _userID;
            }
        }
    }

    #endregion

    #region MessageNotFoundException

    /// <summary>
    /// This exception is thrown when a Message is not found. 
    /// </summary>
    public class MessageNotFoundException : Exception
    {
        private int _msgID;

        /// <summary>
        /// Create a new instance of MessageNotFoundException.
        /// </summary>
        /// <param name="msgID">The message's id that was not found.</param>
        public MessageNotFoundException(int msgID)
        {
            _msgID = msgID;
        }

        /// <summary>
        /// Gets the Message of the exception.
        /// </summary>
        public override string Message
        {
            get
            {
                return string.Format("No Message exists with id: {0}", _msgID);
            }
        }
    }

    #endregion

    #region NotificationNotFoundException

    /// <summary>
    /// This exception is thrown when a Notification is not found. 
    /// </summary>
    public class NotificationNotFoundException : Exception
    {
        private int _notificationID;

        /// <summary>
        /// Create a new instance of NotificationNotFoundException.
        /// </summary>
        /// <param name="notificationID">The notification's id that was not found.</param>
        public NotificationNotFoundException(int notificationID)
        {
            _notificationID = notificationID;
        }

        /// <summary>
        /// Gets the Message of the exception.
        /// </summary>
        public override string Message
        {
            get
            {
                return string.Format("No Notification exists with id: {0}", _notificationID);
            }
        }
    }

    #endregion

    #region UserValidationException

    /// <summary>
    /// This exception is thrown when an User is not valid. 
    /// </summary>
    public class UserValidationException : Exception
    {
        /// <summary>
        /// Gets the Message of the exception.
        /// </summary>
        public override string Message
        {
            get
            {
                // TODO: show which fields are invalid.
                return "Some fields should not be null if the user is booked in!";
            }
        }
    }

    #endregion

    #region TripValidationException
    
    /// <summary>
    /// This exception is thrown when a Trip is not valid. 
    /// </summary>
    public class TripValidationException : Exception
    {
        /// <summary>
        /// Create a new instance of EventNotFoundException.
        /// </summary>
        /// <param name="message">The exception message</param>
        public TripValidationException(string message) 
            : base(message)
        {
        }
    }

    #endregion

    #region FieldNotValidException

    /// <summary>
    /// This exception is thrown when a Field is not valid. 
    /// </summary>
    public class FieldNotValidException : Exception
	{
        /// <summary>
        /// Create a new instance of FieldNotValidException.
        /// </summary>
        /// <param name="message">The exception message</param>
        public FieldNotValidException(string message)
            : base(message)
        {
        }
	}

    #endregion

    #region FeedbackValidationException

    /// <summary>
    /// This exception is thrown when a Feedback is not valid. 
    /// </summary>
    public class FeedbackValidationException : Exception
    {
        /// <summary>
        /// Gets the Message of the exception.
        /// </summary>
        public override string Message
        {
            get
            {
                return "Sender reference can't be null!";
            }
        }
    }

    #endregion

    #region MessageValidationException

    /// <summary>
    /// This exception is thrown when a Message is not valid. 
    /// </summary>
    public class MessageValidationException : Exception
    {
        /// <summary>
        /// Gets the Message of the exception.
        /// </summary>
        public override string Message
        {
            get
            {
                return "Sender reference can't be null!";
            }
        }
    }

    #endregion

    #region FieldsNotValidException

    /// <summary>
    /// This class represents the Field info.
    /// </summary>
    public class FieldInfo
    {

        /// <summary>
        /// Get and Set the field name.
        /// </summary>
        public string Name { get; set; }

        /// <summary>
        /// Get and Set the field maximum length.
        /// </summary>
        public int MaxLength { get; set; }

        /// <summary>
        /// Get and Set the field length.
        /// </summary>
        public int Length { get; set; }
    }

    /// <summary>
    /// This exception is thrown when the Fields are not valid. 
    /// </summary>
    public class FieldsNotValidException : Exception
    {

        /// <summary>
        /// Gets the Message of the exception.
        /// </summary>
        public override string Message
        {
            get
            {
                return buildMessage();
            }
        }

        /// <summary>
        /// Creata the message exception.
        /// </summary>
        /// <returns></returns>
        private string buildMessage()
        {
            StringBuilder result = new StringBuilder();
            result.AppendLine("Some NVarChar fields are not valid:");

            _invalidFields.ToList()
                .ForEach(f => result.Append(string.Format("Name = {0}, Length = {1}, MaxLength = {2}",
                        f.Name, f.Length, f.MaxLength)));

            return result.ToString();
        }

        private IEnumerable<FieldInfo> _invalidFields;

        /// <summary>
        /// Create a new instance of FieldsNotFoundException.
        /// </summary>
        /// <param name="invalidFields">The set of the invalid fields.</param>
        public FieldsNotValidException(IEnumerable<FieldInfo> invalidFields)
        {
            _invalidFields = invalidFields;
        }
    }

    #endregion
}
